﻿# 简单的HTTP服务器脚本，用于提供静态文件服务
#  有中文编码，必须以UTF-BOM格式保存
# 设置侦听url, 端口号, 当前运行路径
$port = 5173
$url = "http://localhost:$port/"
$root = (Get-Item -Path .).FullName

# 权限处理函数 ===============================================================================
# 检查是否已设置URL ACL
function Test-UrlAcl {
    try {
        $result = netsh http show urlacl url="http://*:$port/" 2>&1 | Out-String
        return $result -notlike "*找不到元素*"
    } catch {
        return $false
    }
}
# 添加URL ACL
function Add-UrlAcl {
    try {
        netsh http add urlacl url="http://*:$port/" user=Everyone 2>&1 | Out-Null
        return $true
    } catch {
        return $false
    }
}
# 检查当前是否具有管理员权限
function Test-Admin {
    $currentUser = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
    return $currentUser.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}





# main ==================================================================
# 如果没有管理员权限且URL ACL未设置，则尝试添加
if (-not (Test-UrlAcl)) {
    if (-not (Test-Admin)) {
        Write-Host "需要管理员权限来设置URL ACL"
        Write-Host "请以管理员身份运行此脚本"
        pause
        exit 1
    } else {
        Write-Host "正在设置URL ACL..."
        if (-not (Add-UrlAcl)) {
            Write-Host "设置URL ACL失败"
            pause
            exit 1
        }
        Write-Host "URL ACL设置成功"
    }
}

try {
    # 创建HttpListener对象
    $listener = New-Object System.Net.HttpListener
    # $listener.Prefixes.Add("http://localhost:$port/")
    # $listener.Prefixes.Add("http://127.0.0.1:$port/")
    # $listener.Prefixes.Add("http://192.168.1.157:$port/")
    $listener.Prefixes.Add("http://*:$port/")
    # 开始监听
    $listener.Start()
}
catch {
    Write-Host "启动服务器失败: $($_.Exception.Message)"
    exit 1
}
Write-Host "Server running at http://localhost:$port/"
Write-Host "Server running at http://127.0.0.1:$port/"

# 处理请求的循环
while ($listener.IsListening) {
    # 异步获取请求
    $context = $listener.GetContext()
    $request = $context.Request
    $response = $context.Response
    
    # 获取请求的文件路径
    $relPath = $request.Url.AbsolutePath
    if ($relPath -eq '/') {
        $relPath = '/index.html'
    }
    
    $filePath = [System.IO.Path]::Combine($root, $relPath.Substring(1))
    
    # 检查文件是否存在
    if (Test-Path $filePath -PathType Leaf) {
        # 读取文件内容
        $buffer = [System.IO.File]::ReadAllBytes($filePath)
        
        # 设置内容类型
        $response.ContentType = switch ([System.IO.Path]::GetExtension($filePath)) {
            '.html' { 'text/html' }
            '.js'   { 'text/javascript' }
            '.css'  { 'text/css' }
            '.png'  { 'image/png' }
            '.jpg'  { 'image/jpeg' }
            '.gif'  { 'image/gif' }
            '.ico'  { 'image/x-icon' }
            default { 'application/octet-stream' }
        }
        
        $response.ContentLength64 = $buffer.Length
        $response.OutputStream.Write($buffer, 0, $buffer.Length)
    } else {
        # 文件不存在，返回404
        $response.StatusCode = 404
        $buffer = [System.Text.Encoding]::UTF8.GetBytes('File not found')
        $response.ContentLength64 = $buffer.Length
        $response.OutputStream.Write($buffer, 0, $buffer.Length)
    }
    
    # 关闭响应
    $response.Close()
}

# 停止监听
$listener.Stop()